package handler

import (
	"context"
	"family-doctor/common/consts"
	"family-doctor/common/models"
	"family-doctor/common/proto/familyDoctor"
	"fmt"
	"github.com/cheng1005/XxCh-Common/common/global"
	"github.com/cheng1005/XxCh-Common/pkg"
	"github.com/google/uuid"
	"strconv"
	"time"
)

type Server struct {
	familyDoctor.UnimplementedFamilyDoctorSrvServer
}

func (s *Server) UserLogin(_ context.Context, req *familyDoctor.UserLoginRequest) (*familyDoctor.Response, error) {

	//if global.RDB.Get(context.Background(), "smsCode").Val() != req.Code {
	//	return nil, fmt.Errorf("code error")
	//}

	var user models.Users
	global.DB.Where("phone = ?", req.Phone).Find(&user)
	if user.Id == 0 {
		newUser := models.Users{
			Phone: req.Phone,
		}
		global.DB.Create(&newUser)
		return &familyDoctor.Response{
			UserId: newUser.Id,
		}, nil
	} else {

		return &familyDoctor.Response{
			UserId: user.Id,
		}, nil
	}

}

// EntityList 机构列表
func (s *Server) EntityList(_ context.Context, req *familyDoctor.EntityListRequest) (*familyDoctor.EntityListResponse, error) {
	page := req.Page
	if page <= 0 {
		page = 1
	}

	pageSize := req.Size
	switch {
	case pageSize > 100:
		pageSize = 100
	case pageSize <= 0:
		pageSize = 10
	}

	offset := (page - 1) * pageSize

	query := global.DB.Model(&models.Entitys{})
	if req.KeyWord != "" {
		query.Where("name like ?", "%"+req.KeyWord+"%")
	}

	var entities []models.Entitys
	query.Offset(int(offset)).Limit(int(pageSize)).Find(&entities)

	var entityList []*familyDoctor.EntityList
	for _, entity := range entities {
		entityList = append(entityList, &familyDoctor.EntityList{
			EntityId: entity.Id,
			Name:     entity.Name,
		})
	}

	return &familyDoctor.EntityListResponse{
		EntityList: entityList,
	}, nil
}

// EntityInfo 机构详情
func (s *Server) EntityInfo(_ context.Context, req *familyDoctor.EntityInfoRequest) (*familyDoctor.EntityInfoResponse, error) {

	var entity models.Entitys
	global.DB.Where("id =?", req.EntityId).Find(&entity)
	if entity.Id == 0 {
		return nil, fmt.Errorf("entity not found")
	}

	return &familyDoctor.EntityInfoResponse{
		EntityId: entity.Id,
		Name:     entity.Name,
		Phone:    entity.Phone,
		Address:  entity.Address,
		Text:     entity.Text,
	}, nil
}

// DoctorInfo 医生详情
func (s *Server) DoctorInfo(_ context.Context, req *familyDoctor.DoctorInfoRequest) (*familyDoctor.DoctorInfoResponse, error) {

	var doctor models.Doctors
	global.DB.Where("id =?", req.DoctorId).Find(&doctor)
	if doctor.Id == 0 {
		return nil, fmt.Errorf("doctor not found")
	}

	return &familyDoctor.DoctorInfoResponse{
		DoctorId:   doctor.Id,
		Name:       doctor.Name,
		Phone:      doctor.Phone,
		PositionId: doctor.PositionId,
		Text:       doctor.Text,
	}, nil
}

// DoctorList 医生列表
func (s *Server) DoctorList(_ context.Context, req *familyDoctor.DoctorListRequest) (*familyDoctor.DoctorListResponse, error) {

	var doctors []models.Doctors
	global.DB.Find(&doctors)
	var doctorList []*familyDoctor.DoctorList
	for _, v := range doctors {
		doctorList = append(doctorList, &familyDoctor.DoctorList{
			DoctorId: v.Id,
			Name:     v.Name,
		})
	}
	return &familyDoctor.DoctorListResponse{
		DoctorList: doctorList,
	}, nil
}

func (s *Server) OrderCreate(_ context.Context, req *familyDoctor.OrderCreateRequest) (*familyDoctor.OrderCreateResponse, error) {
	var user models.Users
	global.DB.Where("id =?", req.UserId).Find(&user)
	if user.Id == 0 {
		return nil, fmt.Errorf("user not found")
	}
	var doctor models.Doctors
	global.DB.Where("id =?", req.DoctorId).Find(&doctor)
	if doctor.Id == 0 {
		return nil, fmt.Errorf("doctor not found")
	}
	//分布式锁
	key := fmt.Sprintf("orderLock:userId:%d", doctor.Id)
	lockVlaue := user.Phone + time.Now().Format("20060102150405")

	global.RDB.SetNX(context.Background(), key, lockVlaue, 10)

	defer global.RDB.Del(context.Background(), key)
	
	//开启事务
	tx := global.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	number := uuid.NewString()
	newOrder := models.Orders{
		Number:   number,
		UserId:   req.UserId,
		DoctorId: req.DoctorId,
		Price:    doctor.Price,
		PayTypes: req.PayTypes,
	}
	if err := tx.Create(&newOrder).Error; err != nil {
		return nil, fmt.Errorf("create order failed")
		tx.Rollback()
	}

	if req.PayTypes == consts.OnlinePay {
		//todo 在线支付
		payUrl := pkg.AliPay(doctor.Name, number, strconv.FormatUint(doctor.Price, 10))

		tx.Commit()
		return &familyDoctor.OrderCreateResponse{
			PayUrl: payUrl,
		}, nil
	} else if req.PayTypes == consts.BalancePay {
		//todo 余额支付
		user.TotalNum -= doctor.Price

		if err := tx.Updates(user).Error; err != nil {
			return nil, fmt.Errorf("update user failed")
			tx.Rollback()
		}

	} else {
		return nil, fmt.Errorf("pay types error")
		tx.Rollback()
	}
	tx.Commit()
	return &familyDoctor.OrderCreateResponse{
		PayUrl: "success",
	}, nil
}
